function LpCore() {

    const fs = require('fs');
    const path = require('path');
    var p_sTargetFilePath = "";
    var p_oLpRule = null;

    return {

        getTargetFilePath: function () {
            return p_sTargetFilePath;
        },

        setTargetFilePath: function (path) {
            p_sTargetFilePath = path;
            return this;
        },

        getLpRule: function () {
            return p_oLpRule;
        },

        setLpRule: function (oLpRule) {
            p_oLpRule = oLpRule;
            return this;
        },

        /**
         * oFileParseResult schema { rows: [] }
         * @param {*} sFileName 
         * @param {*} p_oLpRule 
         */
        parseWrapper: function (sFileName, p_oLpRule) {
            var oLocLpRule = p_oLpRule;
            if (!p_oLpRule) {
                oLocLpRule = this.getLpRule();
            }
            if (!oLocLpRule) {
                throw new Error("Mandatory parse rule not set");
            }
            var sFilePath = path.resolve(sFileName);
            process.argv.forEach((val, index) => {
                if (index === 2 && val !== null) {
                    sFilePath = val;
                }
            });
            var sLogs = fs.readFileSync(sFilePath, 'utf8');
            var aLogs = this.getLpRule().fnSplitEntry(sLogs);
            var oFileParseResult = { rows: [] };
            var iCount = 0;
            for (let i = 0; i < aLogs.length; i++) {
                const sLog = aLogs[i];
                var oLineParseResult = this.getLpRule().fnPaserLine(sLog, oFileParseResult);
                if (!oLineParseResult) {
                    continue;
                }
                iCount++;
                oFileParseResult.rows.push(oLineParseResult);
            }
            var sLocSuffix = oLocLpRule.getRuleName()
            if (!sLocSuffix) {
                sLocSuffix = "";
            }
            this.setTargetFilePath(`${sFilePath}-${sLocSuffix}.json`);
            fs.writeFileSync(this.getTargetFilePath(), JSON.stringify(oFileParseResult));
            return this;
        },

        calcWrapper: function (p_oLpRule) {
            var oLocLpRule = p_oLpRule;
            if (!p_oLpRule) {
                oLocLpRule = this.getLpRule();
            }
            if (!oLocLpRule) {
                throw new Error("Mandatory calc rule not set");
            }
            var oFileParseResult = JSON.parse(fs.readFileSync(this.getTargetFilePath(), 'utf8'));
            var sLocCalcName = oLocLpRule.getCurrentCalc();
            if (!sLocCalcName) {
                throw new Error("Mandatory calc name not set");
            }
            var mAggregate = {};
            var oContext = {
                json: oFileParseResult,
                aggregation: mAggregate,
                rowId: 0
            };
            for (let i = 0; i < oFileParseResult.rows.length; i++) {
                oContext.rowId = i;
                var kv = oLocLpRule.fnCalc(sLocCalcName, oFileParseResult.rows[i], oContext);
                if (!mAggregate[kv.key]) {
                    mAggregate[kv.key] = 0;
                }
                mAggregate[kv.key] = mAggregate[kv.key] + kv.value;
            }
            var sHeader = "";
            var iCount = 0;
            for (var prop in mAggregate) {
                var sLine = prop + "," + mAggregate[prop];
                iCount++;
                sHeader += sLine + "\n";
            }
            fs.writeFileSync(`${this.getTargetFilePath()}-${sLocCalcName}.csv`, sHeader);
            return this;
        }
    };
}

module.exports = LpCore;